/*
 * Copyright (C) 2012 mAPPn.Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mol.market.common.widget;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;

import com.mol.market.R;
import com.mol.market.R.color;
import com.mol.market.Session;
import com.mol.market.common.vo.TagsInfo;

/**
 * 分类的View，用于显示分类的标签。
 * @author Chaos	
 * @since 0.9.6
 * @date 2012-10-16
 */
public class CategoryTagView extends ViewGroup implements OnClickListener{
    
    /**
     * 整个控件和其他控件的距离(dip)
     */
    private static final int MARGIN_RIGHT  = 9;
    private static final int MARGIN_BOTTOM = 9;
    private static final int MARGIN_LEFT   = 9;
    private static final int MARGIN_TOP    = 9;
    
    /**
     * 每个格子的距离(dip)
     */
    private static final int PADDING_LEFT_RIGHT  = 10;
    private static final int PADDING_TOP_BOTTOM  = 10;
    /**
     * TextView里文字的Padding(dip)
     */
    private static final int TEXT_PADDING_LEFT  = 12;
    private static final int TEXT_PADDING_RIGHT = 12;
    private static final int TEXT_PADDING_TOP  = 4;
    private static final int TEXT_PADDING_BOTTOM = 4;
    
    /**
     * 整个Item的高度
     */
    private static final int HEIGHT_LABEL = 72;
    /**
     * 字体大小(Sp)
     */
    private int mTextSize = 15;
    
    private Context mContext = null;
    private Session mSession = null;
    
    private List<Location> mLocationList = null;
    
    /**
     * 对齐方式
     */
    private Alignment mAlignment = Alignment.LEFT;
    /**
     * 省略方式
     */
    private TruncateAt mEllipsize = TruncateAt.END;
    /**
     * tag 监听器
     */
    private TagViewListener mListener = null;
    /**
     * empty view
     */
    private View mEmptyView = null;
    /**
     * 是否已经设置了数据
     */
    private boolean mAlreadySetData = false;
    /**
     * 是否存在EmptyView
     */
    private boolean mIsExistEmptyView = false;
    
    private Config mConfig;
    
    /**
     * @param context
     * @param attrs
     * @param defStyle
     */
    public CategoryTagView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
        
//        TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.CategoryTagView); 
    }

    /**
     * @param context
     * @param attrs
     */
    public CategoryTagView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    /**
     * @param context
     */
    public CategoryTagView(Context context) {
        super(context);
        init(context);
    }
    
    private void init(Context context){
        
        super.setBackgroundColor(getResources().getColor(R.color.tran));
        
        mConfig = new Config();
        
        mSession = Session.get(context);
        mContext = context;
        mLocationList = new ArrayList<CategoryTagView.Location>();
        
        if(getChildCount() != 0){
            throw new IllegalArgumentException("Not allowed to add child in XML");
        }
        
        mEmptyView = createTextView("暂无标签", new TagsInfo().setTagName("暂无标签"));
        this.addView(mEmptyView);
        
        mIsExistEmptyView = true;
    }
    /**
     * 设置数据源，当已有数据时，此方法失效,
     * 请调用 {@link CategoryTagView#changeTags(List)})}
     * @param tags
     * @return set success return true;
     */
    public boolean setTags(List<TagsInfo> list){
        if(mAlreadySetData){
            return false;
        }
        
        if (mIsExistEmptyView) {
            removeView(mEmptyView);
            mIsExistEmptyView = false;
        }
        
        if(addEmptyViewIfNeed(list)){
            mAlreadySetData = false;
            mIsExistEmptyView = true;
            return false;
        }else{
            mAlreadySetData = true;
            addTagView(list);
            return true;
        }
    }
    
    /**
     * 添加TagView
     * @param list
     */
    private void addTagView(List<TagsInfo> list){
        for(TagsInfo tags:list){
            addView(createTextView(tags.getTagName(),tags));
        }
    }
    
    /**
     * 增加空的View
     * @param list
     * @return if add view return true.
     */
    private boolean addEmptyViewIfNeed(List<TagsInfo> list){
        if(list == null || list.size() == 0){
            this.addView(mEmptyView);
            return true;
        }
        return false;
    }
    
    /**
     * 已有数据时，请调用此方法更新数据
     * @param tags
     */
    public void changeTags(List<TagsInfo> list){
        this.removeAllViews();
        mAlreadySetData = false;
        setTags(list);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        
        //first, clear the list.
        mLocationList.clear();

        final int totalWidth = MeasureSpec.getSize(widthMeasureSpec);
        
        int childX = parseDip(MARGIN_LEFT);
        int childY = parseDip(MARGIN_TOP);
        
        int selfHeight = 0;
        
        final int count = getChildCount();
        
        for (int i = 0; i < count; i++) {

            // measure child
            final View view = getChildAt(i);
            view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            
            final int width = view.getMeasuredWidth();
            final int height = view.getMeasuredHeight();
            
            if (childX + width + parseDip(MARGIN_RIGHT) > totalWidth) {
                //(当前坐标 + 要摆放的子控件的宽度 + 和右边的Margin)超过了屏幕的宽度
                if(emsIfNeed(width, height, totalWidth, view, childY, mLocationList)){
                    //进行了EMS
                    childY = childY + height + parseDip(PADDING_TOP_BOTTOM);
                    continue;
                }
                
                childX = parseDip(MARGIN_LEFT);
                childY = childY + height + parseDip(PADDING_TOP_BOTTOM);
            }
            // the child location:
            mLocationList.add(new Location().setStartX(childX).setStartY(childY)
                    .setEndX(childX + width).setEndY(childY + height));
            
            childX = childX + width + parseDip(PADDING_LEFT_RIGHT);
            
            if(i == count - 1){
                selfHeight = childY + height + parseDip(MARGIN_BOTTOM);
            }
        }
        setMeasuredDimension(totalWidth, selfHeight);
    }
    
    /**
     * ems tags
     * @return if ems return true
     */
    private boolean emsIfNeed(int width, int height, int totalWidth, View view, int childY,
            List<Location> list) {
        if(width + parseDip(MARGIN_LEFT) > totalWidth){
            //如果自身已经超过了屏幕限制，只能尽最大努力去显示。
            if(!(view instanceof TextView)){
                throw new RuntimeException("Unpredictable errors");
            }
            TextView tv = (TextView)view;
            tv.setEllipsize(mEllipsize); 
            tv.setSingleLine(true);
            tv.setWidth(totalWidth - parseDip(MARGIN_LEFT) - parseDip(MARGIN_RIGHT));
            list.add(new Location()
                        .setStartX(parseDip(MARGIN_LEFT))
                        .setStartY(childY)
                        .setEndX(totalWidth - parseDip(MARGIN_RIGHT))
                        .setEndY(childY + height));
            return true;
        }
        return false;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        
        final int childCount = getChildCount();
        
        alignIfNeed(mLocationList,l,r);
        
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);
            final Location location = mLocationList.get(i);
            setup(child, location.getStartX(), location.getStartY(), location.getEndX(),
                    location.getEndY());
        }
        
    }
    
    /**
     * 组装child
     * @param child
     * @param sx
     * @param sy
     * @param ex
     * @param ey
     */
    private void setup(View child,int sx,int sy,int ex,int ey){
        child.layout(sx, sy, ex, ey);
    }
    
    /**
     * 如果需要，就重新排列。
     * @param locationList
     * @param l
     * @param r
     */
    private void alignIfNeed(List<CategoryTagView.Location> locationList,int l,int r){

        if(mAlignment == Alignment.LEFT){
            //最初计算得到的就是左对齐，不需要再进行排列了。
            return ;
        }
        //控件总宽度
        int width = r - l;
        //当前遍历控件的高度
        int cellHeight = locationList.get(0).getEndY();
        //需要排序的Location
        List<Location> needOrderList = new ArrayList<CategoryTagView.Location>();
        for (Location loc : locationList) {
            if(loc.getEndY() == cellHeight){
                needOrderList.add(loc);
                continue;
            }
            //需要开始进行排序
            cellHeight = loc.getEndY();
            relocation(needOrderList, width);
            needOrderList.clear();
            needOrderList.add(loc);
        }
        //处理最后一行控件
        if(needOrderList.size() != 0){
            relocation(needOrderList, width);
            needOrderList.clear();
        }
        needOrderList = null;
    }
    
    /**
     * 重新布局
     */
    private void relocation(List<CategoryTagView.Location> needOrderList,int width){
        final int count = needOrderList.size();
        
        //step.1 ：  计算控件占用最宽度
        int cellTotalWidth = needOrderList.get(count - 1).getEndX();
        int offsetX = 0;
        
        if(mAlignment == Alignment.CENTER){
            //step.2 : 总宽度减去占用宽度 ，其值的一半，就是偏移量
            offsetX = (width - cellTotalWidth) / 2;
        }else if(mAlignment == Alignment.RIGHT){
            offsetX = width - cellTotalWidth;
        }
       
        //迭代List，加入偏移量
        for(int i=0; i<count; i++){
            final Location loc = needOrderList.get(i);
            loc.setStartX(loc.getStartX() + offsetX).setEndX(loc.getEndX() + offsetX);
        }
    }
    
    /**
     * create unit label
     * @return
     */
    private TextView createTextView(CharSequence content,TagsInfo tags){
        TextView label = new TextView(mContext);
        label.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, parseDip(HEIGHT_LABEL)));
        label.setBackgroundResource(R.drawable.selector_category_view);
        label.setTextColor(getResources().getColorStateList(R.drawable.selector_category_text));
        label.setClickable(true);
        label.setTextSize(mTextSize);
        label.setPadding(parseDip(TEXT_PADDING_LEFT), 
                         parseDip(TEXT_PADDING_TOP), 
                         parseDip(TEXT_PADDING_RIGHT), 
                         parseDip(TEXT_PADDING_BOTTOM));
        label.setGravity(Gravity.CENTER_VERTICAL);
        label.setText(content);
        label.setTag(tags);
        label.setOnClickListener(this);
        return label;
    }
    
    /**
     * 设置字体大小
     * @param sizeSp
     */
    public boolean setTextSize(int sizeSp){
        if(sizeSp == mTextSize){
            //no need
            return false;
        }
        
        mTextSize = sizeSp;
        
        return resetTextSizeIfNeed(sizeSp);
    }
    
    /**
     * 重置字体大小
     * @param size
     * @return
     */
    private boolean resetTextSizeIfNeed(int size){
        final int count = getChildCount();
        
        if(count == 0){
            //no need
            return false;
        }
        
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            
            if(!(child instanceof TextView)){
                //powerless
                continue ;
            }
            
            TextView tv = (TextView)child;
            tv.setTextSize(size);
        }
        
        return true;
    }
    
    /**
     * 将数值解析成dip
     * @param dip
     * @return
     */
    private int parseDip(int dip){
        return (int) (mSession.density * dip);
    }
    
    @Override
    public final void setOnClickListener(OnClickListener l) {
        throw new RuntimeException(
                "This method is not allowed! please use setTagViewListener(TagViewListener l)");
    }
    
    /**
     * 标签的坐标
     * @author Chaos	
     *
     */
    static class Location{
        
        private int startX;
        private int startY;
        private int endX;
        private int endY;
        
        private int getStartX(){
            return startX;
        }
        
        private int getStartY(){
            return startY;
        }
        
        private int getEndX(){
            return endX;
        }
        
        private int getEndY(){
            return endY;
        }
        
        private Location setStartX(int x){
            this.startX = x;
            return this;
        }
        
        private Location setStartY(int y){
            this.startY = y;
            return this;
        }
        
        private Location setEndX(int x){
            this.endX = x ;
            return this;
        }
        
        private Location setEndY(int y){
            this.endY = y;
            return this;
        }
        
    }
    
    /**
     * 对齐方式
     * @author Chaos	
     */
    enum Alignment{
        //左对齐
        LEFT,
        //中心
        CENTER,
        //右对齐
        RIGHT;
    }

    public TruncateAt getmEllipsize() {
        return mEllipsize;
    }

    public void setmEllipsize(TruncateAt mEllipsize) {
        this.mEllipsize = mEllipsize;
    }

    public Alignment getmAlignment() {
        return mAlignment;
    }

    public void setmAlignment(Alignment mAlignment) {
        this.mAlignment = mAlignment;
    }
    
    public void setTagsViewOnClickListener(TagViewListener listener){
        mListener = listener;
    }
    
    /**
     * it shows this view if there is no data 
     * @deprecated
     * @param emptyView
     */
    public void setEmptyView(View emptyView){
        this.mEmptyView = emptyView;
    }
    
    @Override
    public void onClick(View v) {
        
        if(mListener == null){
            //No one cares about it
            return ;
        }
        
        //Try our best to get tags
        Object tags = v.getTag();
        if(tags != null && (tags instanceof TagsInfo)){
            mListener.onTagsViewClick(v, (TagsInfo) tags);
        }else{
            //unlucky
            mListener.onTagsViewClick(v, null);
        }
        
    }
    
    /**
     * 内部配置信息
     * @author Chaos	
     * @date 2013-1-22
     */
    class Config{
        public int margin_left   = 0;
        public int margin_right  = 0;
        public int margin_bottom = 0;
        public int margin_top    = 0;
        
        /**
         * 每个item之间的距离
         */
        public int padding_left_right = 0;
        public int padding_top_bottom = 0;
        
        public int item_padding_left   = 0;
        public int item_padding_right  = 0;
        public int item_padding_top    = 0;
        public int item_padding_bottom = 0;
        
        public int item_height = 0;
        public int item_width  = 0;
    }
    
    public static interface TagViewListener{
        /**
         * @param v 
         * @param tagsId if can't found, tagsId == null;
         */
        public void onTagsViewClick(View v,TagsInfo tag);
    }
}
